// 组合（Composite Pattern）模式的定义：有时又叫作整体-部分
// （Part-Whole）模式，它是一种将对象组合成树状的层次结构的模式，
// 用来表示“整体-部分”的关系，使用户对单个对象和组合对象具有一致
// 的访问性，属于结构型设计模式。可以类比树结构

//根和树枝节点属于同一类型，叶子属于不同类型

// 组合模式的主要优点有：
// 组合模式使得客户端代码可以一致地处理单个对象和组合对象，
//无须关心自己处理的是单个对象，还是组合对象，这简化了客户端代码；
// 更容易在组合体内加入新的对象，客户端不会因为加入了新的对象
//而更改源代码，满足“开闭原则”；

// 其主要缺点是：
// 设计较复杂，客户端需要花更多时间理清类之间的层次关系；
// 不容易限制容器中的构件；
// 不容易用继承的方法来增加构件的新功能；
import java.util.ArrayList;

public class ShoppingTest {
    public static void main(String[] args) {
        float s = 0;
        Bags BigBag,mediumBag,smallBag,smallWhiteBag;
        Goods sp;
        BigBag = new Bags("大袋子");
        mediumBag = new Bags("中带子");
        smallBag = new Bags("小袋子");
        smallWhiteBag = new Bags("小白袋子");
        sp = new Goods("AA", 2, 7.9f);
        smallBag.add(sp);
        sp = new Goods("BB", 1, 9.9f);
        smallBag.add(sp);
        sp = new Goods("CC", 2, 68);
        smallWhiteBag.add(sp);
        sp = new Goods("DD", 3, 180);
        smallWhiteBag.add(sp);
        sp = new Goods("EE", 1, 380);
        mediumBag.add(sp);
        mediumBag.add(smallBag);
        sp = new Goods("FF", 1, 198);
        BigBag.add(sp);
        BigBag.add(smallWhiteBag);
        BigBag.add(mediumBag);
        System.out.println("您选购的商品有：");
        BigBag.show();
        s = BigBag.calculation();
        System.out.println("要支付的总价是：" + s + "元");
    }
}

//
interface Articles{
    public float calculation();

    public void show();
}

//树叶：商品
class Goods implements Articles{
    private String name;
    private int quantity;
    private float unitPrice;

    public Goods(String name,int quantity,float unitPrice){
        this.name = name;
        this.quantity = quantity;
        this.unitPrice = unitPrice;
    }

    public float calculation(){
        return quantity*unitPrice;
    }

    public void show (){
        System.out.println(name+"(数量："+quantity+",单价："+unitPrice+"元）");
    }
}

//
class Bags implements Articles{
    private ArrayList<Articles> bags = new ArrayList<Articles>();

    public Bags(String name) {
    }

    public void add(Articles c){
        bags.add(c);
    }

    public void remove(Articles c){
        bags.remove(c);
    }

    public Articles getChild(int i){
        //ArrayList的get方法
        return bags.get(i);
    }

    public float calculation(){
        float s=0;
        for(Object obj:bags){
            s+=((Articles)obj).calculation();
        }
        return s;
    }

    public void show(){
        //用法是什么
        for(Object obj:bags){
            ((Articles)obj).show();
        }
    }
}